use std::ops;

#[derive(Clone)]
pub struct LastTen {
    pub data: u64,
}

impl LastTen {
    pub fn new(data: u64) -> LastTen {
        LastTen { data }
    }
    fn reduce(&mut self) {
        let max = 10_000_000_000;
        if self.data >= max {
            self.data %= max;
        }
    }
    pub fn pow(&self, exp: u64) -> LastTen {
        let mut data = self.clone();
        for _ in 1..exp {
            data *= self;
        }
        data
    }
}

impl ops::Add for LastTen {
    type Output = Self;
    fn add(self, other: Self) -> Self {
        let data = self.data + other.data;
        let mut rst = Self { data };
        rst.reduce();
        rst
    }
}

impl ops::AddAssign<&LastTen> for LastTen {
    fn add_assign(&mut self, other: &LastTen) {
        self.data += other.data;
        self.reduce();
    }
}

impl ops::MulAssign<&LastTen> for LastTen {
    fn mul_assign(&mut self, rhs: &LastTen) {
        self.data *= rhs.data;
        self.reduce();
    }
}
